#include "demux.h"
#include "demux_avi.h"
#include "video_stream.h"
#include "audio_stream.h"

VIDEO_ERROR demux_init()
{
	return avi_init();
}

VIDEO_ERROR demux_free()
{
	return avi_free();
}

VIDEO_ERROR demux_file_head()
{
	AVISTATUS res = 0;

	res = avi_get_avi_info(&g_video_context->favi);
	if (res != AVI_OK)return VIDEO_ERROR_08;
	
	res = avi_seek_to_movi(&g_video_context->favi);
	if (res != AVI_OK)return VIDEO_ERROR_08;

	switch (g_avi_context->VideoType)
	{
	case AVI_FORMAT_MJPG:
	case AVI_FORMAT_H264:
		break;
	default:
		return VIDEO_ERROR_14;
	}

	switch (g_avi_context->AudioType)
	{
	case 1:	//pcm
	case 2:	//adpcm_ms
	case 17://adpcm_ima_wav
		break;
	default:
		return VIDEO_ERROR_15;
	}

	return VIDEO_ERROR_OK;
}

#if 0
typedef struct
{
	int header_len;//512
	int outW;//640
	int outH;//480
	int db_en;//1
	int crc;//=0
	int frame_num;//
	int frame_size[512-6];
}FILE_HEADER;

FILE_HEADER ttt={512*4,640,480,1,0,0,0};
FILE* fp = 0;
VIDEO_ERROR demux_next_block1()
{
	VIDEO_ERROR res = 0;
	u32 br;
	FRAME frame = { 0 };
	char buff[200 * 1024];

	if (fp == 0)
	{
		fp = fopen("ttt.h264", "wb");
		fwrite(&ttt, 1, sizeof(FILE_HEADER), fp);
	}

	res = avi_get_block_head(&g_video_context->favi, &frame.h);

	if (res == VIDEO_ERROR_99)
	{
		fseek(fp, 0, 0);
		fwrite(&ttt, 1, sizeof(FILE_HEADER), fp);
		fclose(fp);
		return VIDEO_ERROR_99;
	}
	res = f_read(&g_video_context->favi, buff, frame.h.size, &br);
	assert(res == 0);
	assert(br == frame.h.size);

	if (frame.h.id.id == AVI_VIDS_FLAG0)
	{
		ttt.frame_size[ttt.frame_num] = frame.h.size;
		ttt.frame_num++;
		assert(ttt.frame_num < 500);
		fwrite(buff, 1, frame.h.size, fp);
	}

	return VIDEO_ERROR_OK;

}
#endif

VIDEO_ERROR demux_next_block()
{
	VIDEO_ERROR res = 0;
	FRAME frame = {0};

	res = avi_get_block_head(&g_video_context->favi, &frame.h);
	if (res) return res;

	if (frame.h.size == 0)
		return VIDEO_ERROR_OK;

	switch (frame.h.fccid.id)
	{
	case AVI_AUDS_FLAG0://audio
	case AVI_AUDS_FLAG1://audio
	{
		if (frame.h.size > BUFF_SIZE)
			return VIDEO_ERROR_09;

		frame.buff = mem_get_buff();
		res = avi_get_block_data(&g_video_context->favi, frame.buff, frame.h.size);
		if (res)return res;

		res = audio_stream_frame_out(&frame);
		if (res)return res;

		if (g_video_context->cb)g_video_context->cb(VIDEO_FRAME_A, frame.h.size);
		break;
	}

	case AVI_VIDS_FLAG0://video
	case AVI_VIDS_FLAG1://video
		res = video_stream_frame_out(&frame);
		if (res)return res;
		if (g_video_context->cb)g_video_context->cb(VIDEO_FRAME_V, frame.h.size);
		break;

	default://unknow tag
		break;
	}

	return VIDEO_ERROR_OK;
}

VIDEO_ERROR mux_file_head()
{
	AVISTATUS res = 0;

	// config g_avi_context;
	avi_config();

	res = avi_put_avi_info(&g_video_context->favi);
	if (res != AVI_OK)return VIDEO_ERROR_08;

	res = avi_seek_to_movi(&g_video_context->favi);
	if (res != AVI_OK)return VIDEO_ERROR_08;

	return VIDEO_ERROR_OK;
}

VIDEO_ERROR mux_file_end()
{
	VIDEO_ERROR res = 0;

	res = avi_put_idx1_info(&g_video_context->favi);
	if (res)return res;

	avi_update_file_map(&g_video_context->favi);

	res = avi_put_avi_info(&g_video_context->favi);
	if (res)return res;

	return VIDEO_ERROR_OK;
}

VIDEO_ERROR mux_next_block_a(FRAME* frame)
{
	VIDEO_ERROR res = 0;

	res = avi_put_block_head(&g_video_context->favi, &frame->h);
	if (res)return res;

	res = avi_put_block_data(&g_video_context->favi, frame->buff, frame->h.size);
	if (res)return res;

	res = mux_ensure_alignment();
	if (res)return res;

	return VIDEO_ERROR_OK;
}

VIDEO_ERROR mux_next_block_v(FRAME* frame)
{
	return avi_put_block_head(&g_video_context->favi, &frame->h);
}

VIDEO_ERROR mux_video_pkg(void* buff, u32 len)
{
	VIDEO_ERROR res = 0;
	res = avi_put_block_data(&g_video_context->favi, buff, len);
	if (res)return res;

	g_avi_context->frame_v.h.size += len;

	return VIDEO_ERROR_OK;
}

VIDEO_ERROR mux_ensure_alignment()
{
	return avi_ensure_alignment(&g_video_context->favi);
}
